﻿using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows.Browser;
using System.Windows.Controls;
using MM.Hash.Core;

namespace MM.Hash.UI
{
    public class HashOperator
    {
        private BackgroundWorker worker;
        private TextBox inputFile;
        private Button btnBrowse;
        private ProgressBar pgbHash;

        public FileInfo Target { get; set; }
        public string SHA1 { get; private set; }
        public string ED2K { get; private set; }

        public HashOperator(TextBox inputFile, Button btnBrowse, ProgressBar pgbHash)
        {
            this.inputFile = inputFile;
            this.btnBrowse = btnBrowse;
            this.pgbHash = pgbHash;
            this.worker = new BackgroundWorker();

            worker.WorkerReportsProgress = true;
            worker.DoWork += Worker_DoWork;
            worker.ProgressChanged += Worker_ProgressChanged;
            worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        }


        public void CalculateHash()
        {
            HtmlPage.Window.Invoke("beginCheck");
            inputFile.Text = String.Format("{0} ({1} bytes)", Target.Name, Target.Length.ToString("0,0"));

            btnBrowse.IsEnabled = false;
            pgbHash.Value = 0;

            worker.RunWorkerAsync();
        }


        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pgbHash.Value = (double)e.UserState * 100;
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            // 64k has the best performance!
            const int BLOCK_PIECE = 64 * 1024;

            AsyncSHA1 sha1 = new AsyncSHA1();
            AsyncED2K ed2k = new AsyncED2K();
            byte[] buffer = new byte[BLOCK_PIECE];

            using (Stream s = Target.OpenRead())
            {
                int read = 0;
                int ellapsed = 0;
                do
                {
                    read = s.Read(buffer, 0, BLOCK_PIECE);
                    if (read > 0)
                    {
                        sha1.HashCore(buffer, 0, read);
                        ed2k.HashCore(buffer, 0, read);

                        ellapsed += read;

                        // set percentage to userState instead of percentProgress
                        worker.ReportProgress(0, (ellapsed / (double)Target.Length));
                    }
                }
                while (read > 0);
            }

            SHA1 = BitConverter.ToString(sha1.HashFinal()).Replace("-", "").ToUpper();
            ED2K = BitConverter.ToString(ed2k.HashFinal()).Replace("-", "").ToUpper();
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            btnBrowse.IsEnabled = true;
          
            var callbackData = string.Format("{0}|{1}|{2}", HttpUtility.UrlEncode(Target.Name), SHA1, ED2K);
            HtmlPage.Window.Invoke("endCheck", callbackData);
        }
    }
}
